import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_picker/flutter_picker.dart';
import 'package:image_picker/image_picker.dart';
import 'package:qunaimedical/init/theme.dart';
import 'package:qunaimedical/utils/toast_util.dart';
import 'package:url_launcher/url_launcher.dart';

class CommonUtil {
  CommonUtil._internal();

  /// 判断登录密码：6~16位数字和字符组合
  static bool isLoginPassword(String input) {
    RegExp mobile = RegExp(r"(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$");
    return mobile.hasMatch(input);
  }

  /// 6位数字验证码
  static bool isValidatedCaptcha(String input) {
    RegExp mobile = RegExp(r"\d{6}$");
    return mobile.hasMatch(input);
  }

  /// 邮箱匹配
  static bool isValidatedEmail(String email) {
    var re =
        "[\\w!#\$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#\$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?";
    return RegExp(re).hasMatch(email);
  }

  /// 隐藏键盘
  static void hideKeyboard(BuildContext context) {
    FocusScope.of(context).requestFocus(FocusNode());
  }

  /// 将图片转换成MapEntry，上传使使用。
  static Future<List<MapEntry<String, MultipartFile>>> files2MapEntry(
      List<XFile?> files) async {
    List<MapEntry<String, MultipartFile>> entries = [];
    for (int i = 0; i < files.length; i++) {
      entries.add(
        MapEntry(
          "file",
          await MultipartFile.fromFile(files[i]!.path),
        ),
      );
    }
    return entries;
  }

  /// 判定是否为数字
  static bool isNumeric(String? s) {
    if (s == null) {
      return false;
    }
    return double.tryParse(s) != null;
  }

  /// 统一处理Dio网络请求异常。
  static void catchDioError(DioError e) {
    switch (e.type) {
      case DioErrorType.connectTimeout:
      case DioErrorType.sendTimeout:
      case DioErrorType.receiveTimeout:
        ToastUtil.show("连接超时，请稍后再试");
        break;
      case DioErrorType.response:
        ToastUtil.show("请求出错");
        break;
      case DioErrorType.cancel:
        ToastUtil.show("请求已取消");
        break;
      case DioErrorType.other:
        ToastUtil.show("连接异常，请稍后再试");
        break;
    }
  }

  /// 限制组件在大屏下的显示宽度。
  static Widget generateWidgetOfWideScreen(Widget child) {
    return LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
      if (constraints.maxWidth > 600) {
        return Center(
          child: SizedBox(
            width: 600,
            child: child,
          ),
        );
      } else {
        return child;
      }
    });
  }

  static String getDataSize(int? size) {
    if (size == null) return "0KB";
    if (size < 1024) {
      return "1KB";
    } else if (size < 1024 * 1024) {
      return "${size ~/ 1024}KB";
    } else if (size < 1024 * 1024 * 1024) {
      return "${size / 1024 ~/ 1024}MB";
    } else if (size < 1024 * 1024 * 1024 * 1024) {
      return "${size / 1024 / 1024 ~/ 1024}GB";
    } else {
      return "0KB";
    }
  }

  static Future<void> launchInBrowser(String url) async {
    if (!await launchUrl(
      Uri.parse(url),
      mode: LaunchMode.externalApplication,
    )) {
      throw 'Could not launch $url';
    }
  }

  /// 统一的选择器
  static void showPicker(
    BuildContext context, {
    List? pickerData,
    PickerConfirmCallback? onConfirm,
    List<int>? selectedIndex,
  }) {
    hideKeyboard(context);
    Picker picker = Picker(
        selecteds: selectedIndex,
        itemExtent: 40,
        textStyle: const TextStyle(color: Colors.black, fontSize: 16),
        cancelText: "取消",
        confirmText: "确定",
        cancelTextStyle: const TextStyle(color: Colors.grey, fontSize: 16),
        confirmTextStyle: const TextStyle(color: primaryColor, fontSize: 16),
        height: 240,
        adapter: PickerDataAdapter(pickerData: pickerData),
        changeToFirst: false,
        textAlign: TextAlign.left,
        onConfirm: onConfirm);
    picker.showModal(context);
  }
}

enum FunctionType { video, image }
